/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.rabbitmq.http.client; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.*; import com.rabbitmq.http.client.domain.*; import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.BasicAuthCache; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHeader; import org.apache.http.protocol.HttpContext; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import org.springframework.web.util.UriUtils; import javax.net.ssl.SSLContext; import org.springframework.util.Assert; public class Client { private static final HttpClientBuilderConfigurator NO_OP_HTTP_CLIENT_BUILDER_CONFIGURATOR = new HttpClientBuilderConfigurator() { @Override public HttpClientBuilder configure(HttpClientBuilder builder) { return builder; } }; private RestTemplate rt; private URI rootUri; // // API // /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(String url, String username, String password) throws MalformedURLException, URISyntaxException { this(new URL(url), username, password); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @param configurator {@link HttpClientBuilderConfigurator} to use * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(String url, String username, String password, HttpClientBuilderConfigurator configurator) throws MalformedURLException, URISyntaxException { this(new URL(url), username, password, configurator); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(URL url, String username, String password) throws MalformedURLException, URISyntaxException { this(url, username, password, null, null); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @param configurator {@link HttpClientBuilderConfigurator} to use * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(URL url, String username, String password, HttpClientBuilderConfigurator configurator) throws MalformedURLException, URISyntaxException { this(url, username, password, null, null, configurator); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @param sslConnectionSocketFactory ssl connection factory for http client * @param sslContext ssl context for http client * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ private Client(URL url, String username, String password, SSLConnectionSocketFactory sslConnectionSocketFactory, SSLContext sslContext) throws MalformedURLException, URISyntaxException { Assert.notNull(url); Assert.notNull(username); Assert.notNull(password); this.rootUri = url.toURI(); this.rt = new RestTemplate(getRequestFactory(url, username, password, sslConnectionSocketFactory, sslContext, NO_OP_HTTP_CLIENT_BUILDER_CONFIGURATOR)); this.rt.setMessageConverters(getMessageConverters()); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @param sslContext ssl context for http client * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(URL url, String username, String password, SSLContext sslContext) throws MalformedURLException, URISyntaxException { this(url, username, password, null, sslContext); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://localhost:15672/api/". * @param username the username. * @param password the password * @param sslConnectionSocketFactory ssl connection factory for http client * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ private Client(URL url, String username, String password, SSLConnectionSocketFactory sslConnectionSocketFactory) throws MalformedURLException, URISyntaxException { this(url, username, password, sslConnectionSocketFactory, null); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://guest:guest@localhost:15672/api/". * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(String url) throws MalformedURLException, URISyntaxException { this(url, null, null); } /** * Construct an instance with the provided url and credentials. * @param url the url e.g. "http://guest:guest@localhost:15672/api/". * @throws MalformedURLException for a badly formed URL. * @throws URISyntaxException for a badly formed URL. */ public Client(URL url) throws MalformedURLException, URISyntaxException { this(url, null, null); } private Client(URL url, String username, String password, SSLConnectionSocketFactory sslConnectionSocketFactory, SSLContext sslContext, HttpClientBuilderConfigurator configurator) throws URISyntaxException, MalformedURLException { Assert.notNull(url); Assert.notNull(username); Assert.notNull(password); Assert.notNull(configurator); this.rootUri = url.toURI(); HttpComponentsClientHttpRequestFactory rf = getRequestFactory(url, username, password, sslConnectionSocketFactory, sslContext, configurator); this.rt = new RestTemplate(rf); this.rt.setMessageConverters(getMessageConverters()); } /** * @return cluster state overview */ public OverviewResponse getOverview() { return this.rt.getForObject(uriWithPath("./overview"), OverviewResponse.class); } /** * Performs a basic node aliveness check: declares a queue, publishes a message * that routes to it, consumes it, cleans up. * * @param vhost vhost to use to perform aliveness check in * @return true if the check succeeded */ public boolean alivenessTest(String vhost) { final URI uri = uriWithPath("./aliveness-test/" + encodePathSegment(vhost)); return this.rt.getForObject(uri, AlivenessTestResult.class).isSuccessful(); } /** * @return information about the user used by this client instance */ public CurrentUserDetails whoAmI() { final URI uri = uriWithPath("./whoami/"); return this.rt.getForObject(uri, CurrentUserDetails.class); } /** * Retrieves state and metrics information for all nodes in the cluster. * * @return list of nodes in the cluster */ public List<NodeInfo> getNodes() { final URI uri = uriWithPath("./nodes/"); return Arrays.asList(this.rt.getForObject(uri, NodeInfo[].class)); } /** * Retrieves state and metrics information for individual node. * * @param name node name * @return node information */ public NodeInfo getNode(String name) { final URI uri = uriWithPath("./nodes/" + encodePathSegment(name)); return this.rt.getForObject(uri, NodeInfo.class); } /** * Retrieves state and metrics information for all client connections across the cluster. * * @return list of connections across the cluster */ public List<ConnectionInfo> getConnections() { final URI uri = uriWithPath("./connections/"); return Arrays.asList(this.rt.getForObject(uri, ConnectionInfo[].class)); } /** * Retrieves state and metrics information for individual client connection. * * @param name connection name * @return connection information */ public ConnectionInfo getConnection(String name) { final URI uri = uriWithPath("./connections/" + encodePathSegment(name)); return this.rt.getForObject(uri, ConnectionInfo.class); } /** * Forcefully closes individual connection. * The client will receive a <i>connection.close</i> method frame. * * @param name connection name */ public void closeConnection(String name) { final URI uri = uriWithPath("./connections/" + encodePathSegment(name)); deleteIgnoring404(uri); } /** * Forcefully closes individual connection with a user-provided message. * The client will receive a <i>connection.close</i> method frame. * * @param name connection name */ public void closeConnection(String name, String reason) { final URI uri = uriWithPath("./connections/" + encodePathSegment(name)); MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>(); headers.put("X-Reason", Collections.singletonList(reason)); deleteIgnoring404(uri, headers); } /** * Retrieves state and metrics information for all channels across the cluster. * * @return list of channels across the cluster */ public List<ChannelInfo> getChannels() { final URI uri = uriWithPath("./channels/"); return Arrays.asList(this.rt.getForObject(uri, ChannelInfo[].class)); } /** * Retrieves state and metrics information for all channels on individual connection. * @param connectionName the connection name to retrieve channels * @return list of channels on the connection */ public List<ChannelInfo> getChannels(String connectionName) { final URI uri = uriWithPath("./connections/" + encodePathSegment(connectionName) + "/channels/"); return Arrays.asList(this.rt.getForObject(uri, ChannelInfo[].class)); } /** * Retrieves state and metrics information for individual channel. * * @param name channel name * @return channel information */ public ChannelInfo getChannel(String name) { final URI uri = uriWithPath("./channels/" + encodePathSegment(name)); return this.rt.getForObject(uri, ChannelInfo.class); } public List<VhostInfo> getVhosts() { final URI uri = uriWithPath("./vhosts/"); return Arrays.asList(this.rt.getForObject(uri, VhostInfo[].class)); } public VhostInfo getVhost(String name) { final URI uri = uriWithPath("./vhosts/" + encodePathSegment(name)); return getForObjectReturningNullOn404(uri, VhostInfo.class); } public void createVhost(String name) throws JsonProcessingException { final URI uri = uriWithPath("./vhosts/" + encodePathSegment(name)); this.rt.put(uri, null); } public void deleteVhost(String name) { final URI uri = uriWithPath("./vhosts/" + encodePathSegment(name)); deleteIgnoring404(uri); } public List<UserPermissions> getPermissionsIn(String vhost) { final URI uri = uriWithPath("./vhosts/" + encodePathSegment(vhost) + "/permissions"); UserPermissions[] result = this.getForObjectReturningNullOn404(uri, UserPermissions[].class); return asListOrNull(result); } public List<UserPermissions> getPermissionsOf(String username) { final URI uri = uriWithPath("./users/" + encodePathSegment(username) + "/permissions"); UserPermissions[] result = this.getForObjectReturningNullOn404(uri, UserPermissions[].class); return asListOrNull(result); } public List<UserPermissions> getPermissions() { final URI uri = uriWithPath("./permissions"); UserPermissions[] result = this.getForObjectReturningNullOn404(uri, UserPermissions[].class); return asListOrNull(result); } public UserPermissions getPermissions(String vhost, String username) { final URI uri = uriWithPath("./permissions/" + encodePathSegment(vhost) + "/" + encodePathSegment(username)); return this.getForObjectReturningNullOn404(uri, UserPermissions.class); } public List<ExchangeInfo> getExchanges() { final URI uri = uriWithPath("./exchanges/"); return Arrays.asList(this.rt.getForObject(uri, ExchangeInfo[].class)); } public List<ExchangeInfo> getExchanges(String vhost) { final URI uri = uriWithPath("./exchanges/" + encodePathSegment(vhost)); final ExchangeInfo[] result = this.getForObjectReturningNullOn404(uri, ExchangeInfo[].class); return asListOrNull(result); } public ExchangeInfo getExchange(String vhost, String name) { final URI uri = uriWithPath("./exchanges/" + encodePathSegment(vhost) + "/" + encodePathSegment(name)); return this.getForObjectReturningNullOn404(uri, ExchangeInfo.class); } public void declareExchange(String vhost, String name, ExchangeInfo info) { final URI uri = uriWithPath("./exchanges/" + encodePathSegment(vhost) + "/" + encodePathSegment(name)); this.rt.put(uri, info); } public void deleteExchange(String vhost, String name) { this.deleteIgnoring404(uriWithPath("./exchanges/" + encodePathSegment(vhost) + "/" + encodePathSegment(name))); } public List<QueueInfo> getQueues() { final URI uri = uriWithPath("./queues/"); return Arrays.asList(this.rt.getForObject(uri, QueueInfo[].class)); } public List<QueueInfo> getQueues(String vhost) { final URI uri = uriWithPath("./queues/" + encodePathSegment(vhost)); final QueueInfo[] result = this.getForObjectReturningNullOn404(uri, QueueInfo[].class); return asListOrNull(result); } public QueueInfo getQueue(String vhost, String name) { final URI uri = uriWithPath("./queues/" + encodePathSegment(vhost) + "/" + encodePathSegment(name)); return this.getForObjectReturningNullOn404(uri, QueueInfo.class); } public void declarePolicy(String vhost, String name, PolicyInfo info) { final URI uri = uriWithPath("./policies/" + encodePathSegment(vhost) + "/" + encodePathSegment(name)); this.rt.put(uri, info); } public void declareQueue(String vhost, String name, QueueInfo info) { final URI uri = uriWithPath("./queues/" + encodePathSegment(vhost) + "/" + encodePathSegment(name)); this.rt.put(uri, info); } public void purgeQueue(String vhost, String name) { this.deleteIgnoring404(uriWithPath("./queues/" + encodePathSegment(vhost) + "/" + encodePathSegment(name) + "/contents/")); } public void deleteQueue(String vhost, String name) { this.deleteIgnoring404(uriWithPath("./queues/" + encodePathSegment(vhost) + "/" + encodePathSegment(name))); } public void deletePolicy(String vhost, String name) { this.deleteIgnoring404(uriWithPath("./policies/" + encodePathSegment(vhost) + "/" + encodePathSegment(name))); } public List<UserInfo> getUsers() { final URI uri = uriWithPath("./users/"); return Arrays.asList(this.rt.getForObject(uri, UserInfo[].class)); } public UserInfo getUser(String username) { final URI uri = uriWithPath("./users/" + encodePathSegment(username)); return this.getForObjectReturningNullOn404(uri, UserInfo.class); } public void createUser(String username, char[] password, List<String> tags) { if(username == null) { throw new IllegalArgumentException("username cannot be null"); } if(password == null) { throw new IllegalArgumentException("password cannot be null or empty. If you need to create a user that " + "will only authenticate using an x509 certificate, use createUserWithPasswordHash with a blank hash."); } Map<String, Object> body = new HashMap<String, Object>(); body.put("password", new String(password)); body.put("tags", joinStrings(",", tags)); final URI uri = uriWithPath("./users/" + encodePathSegment(username)); this.rt.put(uri, body); } public void createUserWithPasswordHash(String username, char[] passwordHash, List<String> tags) { if(username == null) { throw new IllegalArgumentException("username cannot be null"); } // passwordless authentication is a thing. See // https://github.com/rabbitmq/hop/issues/94 and https://www.rabbitmq.com/authentication.html. MK. if(passwordHash == null) { passwordHash = "".toCharArray(); } Map<String, Object> body = new HashMap<String, Object>(); body.put("password_hash", String.valueOf(passwordHash)); body.put("tags", joinStrings(",", tags)); final URI uri = uriWithPath("./users/" + encodePathSegment(username)); this.rt.put(uri, body); } public void updateUser(String username, char[] password, List<String> tags) { if(username == null) { throw new IllegalArgumentException("username cannot be null"); } Map<String, Object> body = new HashMap<String, Object>(); // only update password if provided if(password != null) { body.put("password", new String(password)); } body.put("tags", joinStrings(",", tags)); final URI uri = uriWithPath("./users/" + encodePathSegment(username)); this.rt.put(uri, body); } public void deleteUser(String username) { this.deleteIgnoring404(uriWithPath("./users/" + encodePathSegment(username))); } public void updatePermissions(String vhost, String username, UserPermissions permissions) { final URI uri = uriWithPath("./permissions/" + encodePathSegment(vhost) + "/" + encodePathSegment(username)); this.rt.put(uri, permissions); } public void clearPermissions(String vhost, String username) { final URI uri = uriWithPath("./permissions/" + encodePathSegment(vhost) + "/" + encodePathSegment(username)); deleteIgnoring404(uri); } public List<PolicyInfo> getPolicies() { final URI uri = uriWithPath("./policies/"); return Arrays.asList(this.rt.getForObject(uri, PolicyInfo[].class)); } public List<PolicyInfo> getPolicies(String vhost) { final URI uri = uriWithPath("./policies/" + encodePathSegment(vhost)); final PolicyInfo[] result = this.getForObjectReturningNullOn404(uri, PolicyInfo[].class); return asListOrNull(result); } public List<BindingInfo> getBindings() { final URI uri = uriWithPath("./bindings/"); return Arrays.asList(this.rt.getForObject(uri, BindingInfo[].class)); } public List<BindingInfo> getBindings(String vhost) { final URI uri = uriWithPath("./bindings/" + encodePathSegment(vhost)); return Arrays.asList(this.rt.getForObject(uri, BindingInfo[].class)); } /** * Returns a list of bindings where provided exchange is the source (other things are * bound to it). * * @param vhost vhost of the exchange * @param exchange source exchange name * @return list of bindings */ public List<BindingInfo> getBindingsBySource(String vhost, String exchange) { final String x = exchange.equals("") ? "amq.default" : exchange; final URI uri = uriWithPath("./exchanges/" + encodePathSegment(vhost) + "/" + encodePathSegment(x) + "/bindings/source"); return Arrays.asList(this.rt.getForObject(uri, BindingInfo[].class)); } /** * Returns a list of bindings where provided exchange is the destination (it is * bound to another exchange). * * @param vhost vhost of the exchange * @param exchange destination exchange name * @return list of bindings */ public List<BindingInfo> getExchangeBindingsByDestination(String vhost, String exchange) { final String x = exchange.equals("") ? "amq.default" : exchange; final URI uri = uriWithPath("./exchanges/" + encodePathSegment(vhost) + "/" + encodePathSegment(x) + "/bindings/destination"); final BindingInfo[] result = this.rt.getForObject(uri, BindingInfo[].class); return asListOrNull(result); } /** * Returns a list of bindings where provided queue is the destination. * * @param vhost vhost of the exchange * @param queue destination queue name * @return list of bindings */ public List<BindingInfo> getQueueBindings(String vhost, String queue) { final URI uri = uriWithPath("./queues/" + encodePathSegment(vhost) + "/" + encodePathSegment(queue) + "/bindings"); final BindingInfo[] result = this.rt.getForObject(uri, BindingInfo[].class); return asListOrNull(result); } public List<BindingInfo> getQueueBindingsBetween(String vhost, String exchange, String queue) { final URI uri = uriWithPath("./bindings/" + encodePathSegment(vhost) + "/e/" + encodePathSegment(exchange) + "/q/" + encodePathSegment(queue)); final BindingInfo[] result = this.rt.getForObject(uri, BindingInfo[].class); return asListOrNull(result); } public List<BindingInfo> getExchangeBindingsBetween(String vhost, String source, String destination) { final URI uri = uriWithPath("./bindings/" + encodePathSegment(vhost) + "/e/" + encodePathSegment(source) + "/e/" + encodePathSegment(destination)); final BindingInfo[] result = this.rt.getForObject(uri, BindingInfo[].class); return asListOrNull(result); } public void bindQueue(String vhost, String queue, String exchange, String routingKey) { bindQueue(vhost, queue, exchange, routingKey, new HashMap<String, Object>()); } public void bindQueue(String vhost, String queue, String exchange, String routingKey, Map<String, Object> args) { if(vhost == null || vhost.isEmpty()) { throw new IllegalArgumentException("vhost cannot be null or blank"); } if(queue == null || queue.isEmpty()) { throw new IllegalArgumentException("queue cannot be null or blank"); } if(exchange == null || exchange.isEmpty()) { throw new IllegalArgumentException("exchange cannot be null or blank"); } Map<String, Object> body = new HashMap<String, Object>(); if(!(args == null)) { body.put("args", args); } body.put("routing_key", routingKey); final URI uri = uriWithPath("./bindings/" + encodePathSegment(vhost) + "/e/" + encodePathSegment(exchange) + "/q/" + encodePathSegment(queue)); this.rt.postForLocation(uri, body); } public void bindExchange(String vhost, String destination, String source, String routingKey) { bindExchange(vhost, destination, source, routingKey, new HashMap<String, Object>()); } public void bindExchange(String vhost, String destination, String source, String routingKey, Map<String, Object> args) { if(vhost == null || vhost.isEmpty()) { throw new IllegalArgumentException("vhost cannot be null or blank"); } if(destination == null || destination.isEmpty()) { throw new IllegalArgumentException("destination cannot be null or blank"); } if(source == null || source.isEmpty()) { throw new IllegalArgumentException("source cannot be null or blank"); } Map<String, Object> body = new HashMap<String, Object>(); if(!(args == null)) { body.put("args", args); } body.put("routing_key", routingKey); final URI uri = uriWithPath("./bindings/" + encodePathSegment(vhost) + "/e/" + encodePathSegment(source) + "/e/" + encodePathSegment(destination)); this.rt.postForLocation(uri, body); } public ClusterId getClusterName() { return this.rt.getForObject(uriWithPath("./cluster-name"), ClusterId.class); } public void setClusterName(String name) { if(name== null || name.isEmpty()) { throw new IllegalArgumentException("name cannot be null or blank"); } final URI uri = uriWithPath("./cluster-name"); Map<String, String> m = new HashMap<String, String>(); m.put("name", name); this.rt.put(uri, m); } @SuppressWarnings({"unchecked","rawtypes"}) public List<Map> getExtensions() { final URI uri = uriWithPath("./extensions/"); return Arrays.asList(this.rt.getForObject(uri, Map[].class)); } public Definitions getDefinitions() { final URI uri = uriWithPath("./definitions/"); return this.rt.getForObject(uri, Definitions.class); } // // Implementation // /** * Produces a URI used to issue HTTP requests to avoid double-escaping of path segments * (e.g. vhost names) from {@link RestTemplate#execute}. * * @param path The path after /api/ * @return resolved URI */ private URI uriWithPath(final String path) { return this.rootUri.resolve(path); } private String encodePathSegment(final String pathSegment) { try { return UriUtils.encodePathSegment(pathSegment, "UTF-8"); } catch (UnsupportedEncodingException e) { // the best we can do without messing up all caller signatures :/ MK. return pathSegment; } } private List<HttpMessageConverter<?>> getMessageConverters() { List<HttpMessageConverter<?>> xs = new ArrayList<HttpMessageConverter<?>>(); final Jackson2ObjectMapperBuilder bldr = Jackson2ObjectMapperBuilder .json() .serializationInclusion(JsonInclude.Include.NON_NULL); xs.add(new MappingJackson2HttpMessageConverter(bldr.build())); return xs; } private HttpComponentsClientHttpRequestFactory getRequestFactory(final URL url, final String username, final String password, final SSLConnectionSocketFactory sslConnectionSocketFactory, final SSLContext sslContext, final HttpClientBuilderConfigurator configurator) throws MalformedURLException { String theUser = username; String thePassword = password; String userInfo = url.getUserInfo(); if (userInfo != null && theUser == null) { String[] userParts = userInfo.split(":"); if (userParts.length > 0) { theUser = userParts[0]; } if (userParts.length > 1) { thePassword = userParts[1]; } } // configure HttpClientBuilder essentials final HttpClientBuilder bldr = HttpClientBuilder.create(). setDefaultCredentialsProvider(getCredentialsProvider(url, theUser, thePassword)); bldr.setDefaultHeaders(Arrays.asList(new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json"))); if (sslConnectionSocketFactory != null) { bldr.setSSLSocketFactory(sslConnectionSocketFactory); } if (sslContext != null) { bldr.setSslcontext(sslContext); } HttpClient httpClient; // this lets the user perform non-essential configuration (e.g. timeouts) // but reduces the risk of essentials not being set. MK. HttpClientBuilder b = configurator.configure(bldr); httpClient = b.build(); // RabbitMQ HTTP API currently does not support challenge/response for PUT methods. AuthCache authCache = new BasicAuthCache(); BasicScheme basicScheme = new BasicScheme(); authCache.put(new HttpHost(rootUri.getHost(), rootUri.getPort(), rootUri.getScheme()), basicScheme); final HttpClientContext ctx = HttpClientContext.create(); ctx.setAuthCache(authCache); return new HttpComponentsClientHttpRequestFactory(httpClient) { @Override protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { return ctx; } }; } private CredentialsProvider getCredentialsProvider(final URL url, final String username, final String password) { CredentialsProvider cp = new BasicCredentialsProvider(); cp.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new UsernamePasswordCredentials(username, password)); return cp; } private <T> T getForObjectReturningNullOn404(final URI uri, final Class<T> klass) { try { return this.rt.getForObject(uri, klass); } catch (final HttpClientErrorException ce) { if(ce.getStatusCode() == HttpStatus.NOT_FOUND) { return null; } else { throw ce; } } } private void deleteIgnoring404(URI uri) { try { this.rt.delete(uri); } catch (final HttpClientErrorException ce) { if(!(ce.getStatusCode() == HttpStatus.NOT_FOUND)) { throw ce; } } } private void deleteIgnoring404(URI uri, MultiValueMap headers) { try { HttpEntity<Object> entity = new HttpEntity<Object>(null, headers); this.rt.exchange(uri, HttpMethod.DELETE, entity, Object.class); } catch (final HttpClientErrorException ce) { if(!(ce.getStatusCode() == HttpStatus.NOT_FOUND)) { throw ce; } } } private <T> List<T> asListOrNull(T[] result) { if(result == null) { return null; } else { return Arrays.asList(result); } } private String joinStrings(String delimiter, List<String> tags) { StringBuilder sb = new StringBuilder(); boolean appendedFirst = false; for (String tag : tags) { if(!appendedFirst) { sb.append(tag); appendedFirst = true; } else { sb.append(delimiter); if(tag != null) { sb.append(tag); } } } return sb.toString(); } }